package com.gome.boot.config.datasource;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据源基础配置.
 *
 * @author baoxiufeng
 */
public class BaseDataSourceConfig {

    private static final String KEY_DATASOURCE_URL = "jdbc.url";
    private static final String KEY_DATASOURCE_USERNAME = "jdbc.username";
    private static final String KEY_DATASOURCE_PASSWORD = "jdbc.password";
    private static final String KEY_DATASOURCE_DRIVER_CLASS_NAME = "jdbc.driver-class-name";
    private static final String KEY_DATASOURCE_MINIDLE = "jdbc.minIdle";
    private static final String KEY_DATASOURCE_MAXWAIT = "jdbc.maxWait";
    private static final String KEY_DATASOURCE_MAXACTIVE = "jdbc.maxActive";
    private static final String KEY_DATASOURCE_INITIALSIZE = "jdbc.initialSize";
    private static final String KEY_DATASOURCE_POOLPREPAREDSTATEMENTS = "jdbc.poolPreparedStatements";
    private static final String KEY_DATASOURCE_MINEVICTABLEIDLETIMEMILLIS = "jdbc.minEvictableIdleTimeMillis";
    private static final String KEY_DATASOURCE_TIMEBETWEENEVICTIONRUNSMILLIS = "jdbc.timeBetweenEvictionRunsMillis";
    private static final String KEY_DATASOURCE_CONNECTIONP_ROPERTY = "jdbc.connection.property";
    private static final String KEY_DATASOURCE_FILTERS = "jdbc.filter";

    @Autowired
    protected Environment env;

    /**
     * 获取数据源实例.
     *
     * @return 数据源实例
     * @throws Exception 异常
     */
    protected DataSource getDataSource() throws Exception {
        return getDataSource(null);
    }

    /**
     * 获取指定类型的数据源实例.
     *
     * @param type 数据源类型
     * @return 数据源实例
     * @throws Exception 异常
     */
    protected DataSource getDataSource(String type) throws Exception {
        DruidDataSource druidDataSource = new DruidDataSource();
        if (type == null) {
            druidDataSource.setUrl(env.getRequiredProperty(KEY_DATASOURCE_URL));
            druidDataSource.setUsername(env.getRequiredProperty(KEY_DATASOURCE_USERNAME));
            druidDataSource.setPassword(env.getRequiredProperty(KEY_DATASOURCE_PASSWORD));
            druidDataSource.setDriverClassName(env.getRequiredProperty(KEY_DATASOURCE_DRIVER_CLASS_NAME));
            druidDataSource.setConnectionProperties(env.getProperty(KEY_DATASOURCE_CONNECTIONP_ROPERTY, "config.decrypt=true"));
        } else {
            druidDataSource.setUrl(env.getRequiredProperty(type + "." + KEY_DATASOURCE_URL));
            druidDataSource.setUsername(env.getRequiredProperty(type + "." + KEY_DATASOURCE_USERNAME));
            druidDataSource.setPassword(env.getRequiredProperty(type + "." + KEY_DATASOURCE_PASSWORD));
            druidDataSource.setDriverClassName(env.getRequiredProperty(type + "." + KEY_DATASOURCE_DRIVER_CLASS_NAME));
            druidDataSource.setConnectionProperties(env.getProperty(type + "." + KEY_DATASOURCE_CONNECTIONP_ROPERTY, "config.decrypt=true"));
        }
        druidDataSource.setMinIdle(env.getProperty(KEY_DATASOURCE_MINIDLE, Integer.class, 2));
        druidDataSource.setMaxWait(env.getProperty(KEY_DATASOURCE_MAXWAIT, Integer.class, 60000));
        druidDataSource.setMaxActive(env.getProperty(KEY_DATASOURCE_MAXACTIVE, Integer.class, 20));
        druidDataSource.setInitialSize(env.getProperty(KEY_DATASOURCE_INITIALSIZE, Integer.class, 2));
        druidDataSource.setPoolPreparedStatements(env.getProperty(KEY_DATASOURCE_POOLPREPAREDSTATEMENTS, Boolean.class, true));
        druidDataSource.setMinEvictableIdleTimeMillis(env.getProperty(KEY_DATASOURCE_MINEVICTABLEIDLETIMEMILLIS, Integer.class, 300000));
        druidDataSource.setTimeBetweenEvictionRunsMillis(env.getProperty(KEY_DATASOURCE_TIMEBETWEENEVICTIONRUNSMILLIS, Integer.class, 600000));
        druidDataSource.setRemoveAbandoned(true);

        StatFilter statFilter = new StatFilter();
        statFilter.setSlowSqlMillis(10000);
        statFilter.setLogSlowSql(true);
        statFilter.setMergeSql(true);

        List<Filter> filters = new ArrayList<>(1);
        filters.add(statFilter);

        druidDataSource.setProxyFilters(filters);
        druidDataSource.setFilters(env.getProperty(KEY_DATASOURCE_FILTERS, "config,wall"));

        return druidDataSource;
    }
}
